home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2001 April / april_2001.iso / intercd / root / ^Palm / Games / eCross / src / eCross.java < prev    next >
Encoding:
Java Source  |  2000-08-01  |  14.9 KB  |  578 lines

  1. /*
  2.  * eCross.java - A GameBoy's "Mario's Picross" clone
  3.  * Copyright (C) 2000 Romain Guy
  4.  * guy.romain@bigfoot.com
  5.  * www.jext.org
  6.  *
  7.  * This program is free software; you can redistribute it and/or
  8.  * modify it under the terms of the GNU General Public License
  9.  * as published by the Free Software Foundation; either version 2
  10.  * of the License, or any later version.
  11.  *
  12.  * This program is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  * GNU General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU General Public License
  18.  * along with this program; if not, write to the Free Software
  19.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  20.  */
  21.  
  22. import waba.io.*;
  23. import waba.fx.*;
  24. import waba.ui.*;
  25. import waba.sys.*;
  26.  
  27. /**
  28.  * eCross is a reflexion game inspired from one, in my humble opinion,
  29.  * of the best Nintendo GameBoy's games: Mario's Picross.<p>
  30.  * In this game, the player has to find out the hidden picture by
  31.  * filling in boxes in a grid according to the informations given next
  32.  * to the game area.
  33.  * @author Romain Guy <guy.romain@bigfoot.com>
  34.  * @version 1.1
  35.  */
  36.  
  37. public class eCross extends MainWindow
  38. {
  39.   ///////////////////////////////////////////////////////////////////////////////////////////////
  40.   // CONSTANTS
  41.   ///////////////////////////////////////////////////////////////////////////////////////////////
  42.   // state
  43.   private static final byte WAIT_FOR_START = 0, LEVEL_FINISHED = 1, PLAYING = 2;
  44.   private byte state = WAIT_FOR_START;
  45.  
  46.   ///////////////////////////////////////////////////////////////////////////////////////////////
  47.   // PRIVATE FIELDS
  48.   ///////////////////////////////////////////////////////////////////////////////////////////////
  49.   // the grid
  50.   private Grid grid;
  51.   // decoration
  52.   private Wall wall;
  53.   // timer
  54.   private BackCounter timer;
  55.   private boolean setTimer;
  56.  
  57.   // levels
  58.   private LevelsManager levels;
  59.   // selector
  60.   private LevelSelector selector;
  61.   // level number
  62.   private int level = 0;
  63.   // the loss in minutes
  64.   private byte loss = -2;
  65.  
  66.   // the title bar
  67.   private Title title;
  68.  
  69.   // tools
  70.   private Tool tool;
  71.   // exit button
  72.   private Exit exit;
  73.   // info
  74.   private Info info;
  75.  
  76.   // drawing area
  77.   private Image bufferImage;
  78.   private Graphics g, bufferGraphics;
  79.  
  80.   ///////////////////////////////////////////////////////////////////////////////////////////////
  81.   // INHERITED METHODS
  82.   ///////////////////////////////////////////////////////////////////////////////////////////////
  83.  
  84.   /**
  85.    * When the application starts, we create the drawing areas
  86.    * and the back buffer (to avoid flickering). We also initialize
  87.    * the grid (game area).
  88.    */
  89.  
  90.   public void onStart()
  91.   {
  92.     // bakc buffering
  93.     g = new Graphics(this);
  94.     bufferImage = new Image(this.width, this.height);
  95.     bufferGraphics = new Graphics(bufferImage);
  96.  
  97.     // splash
  98.     Image splash = new Image("datas/splash.bmp");
  99.     g.drawImage(splash, 16, 4);
  100.     FontMetrics fm = getFontMetrics(this.defaultFont);
  101.     String copyright = new String("(C)2000 Romain Guy - www.jext.org");
  102.     g.drawText(copyright,
  103.                (this.width - fm.getTextWidth(copyright)) / 2,
  104.                this.height - (fm.getHeight() * 2) - 2);
  105.     copyright = new String("(C)2000 Benjamin Rigaud - beno.ctw.cc");
  106.     g.drawText(copyright,
  107.                (this.width - fm.getTextWidth(copyright)) / 2,
  108.                this.height - fm.getHeight());
  109.  
  110.     splash.free();
  111.     splash = null;
  112.  
  113.     Vm.setSystemKeysUse(true);
  114.  
  115.     // GUI
  116.     title = new Title("eCross v1.1");
  117.     title.setRect(0, 0, this.width, 15);
  118.  
  119.     tool = new Tool();
  120.     exit = new Exit();
  121.  
  122.     timer = new BackCounter(this, Wall.PATTERN_WIDTH + 2, 15 + 2 + Wall.PATTERN_HEIGHT);
  123.     tool.setRect(Wall.PATTERN_WIDTH + 2, 15 + 2 + Wall.PATTERN_HEIGHT + 15 + 1, 17, 15);
  124.     exit.setRect(Wall.PATTERN_WIDTH + 2 + 17 + 1, 15 + 2 + Wall.PATTERN_HEIGHT + 15 + 1, 17, 15);
  125.     wall = new Wall(this.width, this.height);
  126.     info = new Info();
  127.  
  128.     grid = new Grid(width  - (15 * Grid.CELL_WIDTH + 16 + Wall.PATTERN_WIDTH  + 2),
  129.                     height - (15 * Grid.CELL_WIDTH + 16 + Wall.PATTERN_HEIGHT + 2),
  130.                     this);
  131.  
  132.     levels = new LevelsManager("eCross Levels.eCrs.eCrs");
  133.     selector = new LevelSelector("eCross Levels.eCrs.eCrs");
  134.     int box = title.getBoxWidth(this);
  135.     selector.setRect(box, 0, this.width - (box + 10 + 1), 15);
  136.  
  137.     Catalog _save = new Catalog("eCross Save.eCrs.eCrs", Catalog.READ_ONLY);
  138.     if (_save.isOpen())
  139.     {
  140.       _save.setRecordPos(0);
  141.  
  142.       // level number
  143.       byte[] b = new byte[1];
  144.       _save.readBytes(b, 0, 1);
  145.       level = (int) b[0];
  146.  
  147.       // level number
  148.       b = new byte[1];
  149.       _save.readBytes(b, 0, 1);
  150.       loss = b[0];
  151.  
  152.       // current time
  153.       b = new byte[2];
  154.       _save.readBytes(b, 0, 2);
  155.       timer.setTime(b[0], b[1]);
  156.       setTimer = true;
  157.  
  158.       // what user did
  159.       b = new byte[15 * 15];
  160.       _save.readBytes(b, 0, b.length);
  161.  
  162.       setLevel();
  163.       grid.setUserLevel(b);
  164.  
  165.       _save.close();
  166.       //_save.delete();
  167.  
  168.     } else
  169.       setLevel();
  170.  
  171.     paint();
  172.     draw();
  173.   }
  174.  
  175.   /**
  176.    * Clears the area and performs painting.
  177.    */
  178.  
  179.   public void onPaint(Graphics g)
  180.   {
  181.     clearBuffer();
  182.     paint();
  183.     //clear();
  184.     draw();
  185.   }
  186.  
  187.   /**
  188.    * Free the resources taken by the drawing areas and saves, if needed, the
  189.    * current game to get back to it later on.
  190.    */
  191.  
  192.   public void onExit()
  193.   {
  194.     if (state == PLAYING)
  195.     {
  196.       byte m = timer.getMinutes();
  197.       byte s = timer.getSeconds();
  198.  
  199.       Catalog _save = new Catalog("eCross Save.eCrs.eCrs", Catalog.CREATE);
  200.       _save.addRecord(1 + 1 + 2 + 15 * 15);
  201.       // level number
  202.       _save.writeBytes(new byte[] { (byte) level }, 0, 1);
  203.       // time loss
  204.       _save.writeBytes(new byte[] { loss }, 0, 1);
  205.       // current time
  206.       _save.writeBytes(new byte[] { m, s }, 0, 2);
  207.       // what user did
  208.       _save.writeBytes(grid.getUserLevel(), 0, 15 * 15);
  209.       _save.close();
  210.     } else {
  211.       Catalog _save = new Catalog("eCross Save.eCrs.eCrs", Catalog.WRITE_ONLY);
  212.       _save.delete();
  213.     }
  214.  
  215.     timer.stop();
  216.  
  217.     clear();
  218.     g.free();
  219.  
  220.     clearBuffer();
  221.     bufferGraphics.free();
  222.     bufferImage.free();
  223.  
  224.     MiniString.free();
  225.     tool.free();
  226.     info.free();
  227.     selector.free();
  228.     wall.free();
  229.   }
  230.  
  231.   /**
  232.    * Handles events from user. Here we catch <code>PEN_UP</code>,
  233.    * <code>PEN_DOWN</code> and <code>KEY_PRESS</code> (this can be
  234.    * done because eCross is targeted to be used with WabaVM 1.0G from
  235.    * <b>Guilherme Hazan</b>).
  236.    * @param event The <code>Event</code> type
  237.    */
  238.  
  239.   public void onEvent(Event event)
  240.   {
  241.     switch (event.type)
  242.     {
  243.       /*
  244.        * PEN UP
  245.        */
  246.       case PenEvent.PEN_UP:
  247.         PenEvent uevt = (PenEvent) event;
  248.  
  249.         // if chooser clicked on info icon or other
  250.         if (info.handlePenUpEvent(g, uevt.x, uevt.y))
  251.         {
  252.           info.showInfo(this, g);
  253.         }
  254.         return;
  255.  
  256.       /*
  257.        * PEN DOWN
  258.        */
  259.       case PenEvent.PEN_DOWN:
  260.         PenEvent evt = (PenEvent) event;
  261.  
  262.         // if user tapped a reactive area
  263.         if (selector.handlePenEvent(this, g, evt.x, evt.y) ||
  264.             info.handlePenEvent(this, g, evt.x, evt.y)     ||
  265.             exit.handlePenEvent(this, g, evt.x, evt.y)       )
  266.         {
  267.           return;
  268.         }
  269.  
  270.         switch (state)
  271.         {
  272.           case WAIT_FOR_START:
  273.             if (timer.state == BackCounter.STOPPED)
  274.             {
  275.               timer.start(setTimer);
  276.               if (setTimer)
  277.                 setTimer = false;
  278.               state = PLAYING;
  279.             }
  280.             break;
  281.           case PLAYING:
  282.             if (tool.handlePenEvent(evt.x, evt.y))
  283.               tool.switchToolForward(this, bufferGraphics);
  284.             else if (!grid.handlePenEvent(tool.getTool(), evt.x, evt.y))
  285.               timer.remove(loss < 8 ? loss += 2 : loss);
  286.             break;
  287.           case LEVEL_FINISHED:
  288.             levelFinished();
  289.             //repaint();
  290.         }
  291.  
  292.         break;
  293.  
  294.       /*
  295.        * KEY PRESSED
  296.        */
  297.       case KeyEvent.KEY_PRESS:
  298.         KeyEvent kevt = (KeyEvent) event;
  299.  
  300.         switch (kevt.key)
  301.         {
  302.           /*
  303.            * HARD KEY 1 PRESSED (agenda)
  304.            */
  305.           case IKeys.HARD1:
  306.             if (state == PLAYING)
  307.               tool.switchToolForward(this, bufferGraphics);
  308.             break;
  309.  
  310.           /*
  311.            * HARD KEY 2 PRESSED (contacts)
  312.            */
  313.           case IKeys.HARD2:
  314.             if (state == PLAYING)
  315.               tool.switchToolBackward(this, bufferGraphics);
  316.             break;
  317.         }
  318.  
  319.         break;
  320.     }
  321.   }
  322.  
  323.   ///////////////////////////////////////////////////////////////////////////////////////////////
  324.   // PUBLIC METHODS
  325.   ///////////////////////////////////////////////////////////////////////////////////////////////
  326.  
  327.   /*
  328.    * Defines some settings to begin a new level.
  329.    */
  330.  
  331.   public void levelFinished()
  332.   {
  333.     loss = -2;
  334.     state = WAIT_FOR_START;
  335.     timer.reset();
  336.     onPaint(g);
  337.   }
  338.  
  339.   /**
  340.    * Re-draws the timer by copying the timer rectangle from back buffered image
  341.    * to screen. This avoids to repaint whole screen every second.
  342.    * @param w The width of the timer
  343.    * @param h The height of the timer
  344.    */
  345.  
  346.   public void drawTimer(int w, int h)
  347.   {
  348.     g.copyRect(bufferImage, Wall.PATTERN_WIDTH + 2, 15 + 2 + Wall.PATTERN_HEIGHT,
  349.                w, h, Wall.PATTERN_WIDTH + 2, 15 + 2 + Wall.PATTERN_HEIGHT);
  350.   }
  351.  
  352.   /**
  353.    * Pauses the counter. Used when showing a modal window
  354.    * such as exit dialog or so.
  355.    */  
  356.  
  357.   public void pauseTimer()
  358.   {
  359.     timer.pause();
  360.   }
  361.  
  362.   /**
  363.    * Resumes the timer count. Called when a modal window
  364.    * is closed.
  365.    */
  366.  
  367.   public void resumeTimer()
  368.   {
  369.     timer.resume();
  370.   }
  371.  
  372.   /**
  373.    * Re-draws the tool by copying the timer rectangle from back buffered image
  374.    * to screen. This avoids to repaint whole screen every second.
  375.    */
  376.  
  377.   public void drawTool()
  378.   {
  379.     g.copyRect(bufferImage, Wall.PATTERN_WIDTH + 2, (15 + 2) * 2 + Wall.PATTERN_HEIGHT,
  380.                17, 15, Wall.PATTERN_WIDTH + 2, (15 + 2) * 2 + Wall.PATTERN_HEIGHT);
  381.   }
  382.  
  383.   /**
  384.    * Sets current level.
  385.    * @param level Level number in defaut levels database
  386.    */
  387.  
  388.   public void setLevel(int level)
  389.   {
  390.     this.level = level;
  391.     setLevel();
  392.   }
  393.  
  394.   /**
  395.    * Returns current level.
  396.    */
  397.  
  398.   public int getLevel()
  399.   {
  400.     return this.level;
  401.   }
  402.  
  403.   /**
  404.    * Called by the grid whenever the player has discovered
  405.    * every single cell of the picture
  406.    * @param picture The level content
  407.    * @param name The level name
  408.    */
  409.  
  410.   public void win(byte[] picture, String name)
  411.   {
  412.     byte m = timer.getMinutes();
  413.     byte s = timer.getSeconds();
  414.  
  415.     timer.stop();
  416.  
  417.     int x = 47;
  418.     int y = 15 + 40;
  419.  
  420.     bufferGraphics.setColor(255, 255, 255);
  421.     bufferGraphics.fillRect(x - 1, y - 1, 64, 64);
  422.  
  423.     bufferGraphics.setColor(0, 0, 0);
  424.     bufferGraphics.drawRect(x, y, 62, 62);
  425.     bufferGraphics.drawRect(x + 16, y + 16, 31, 31);
  426.  
  427.     bufferGraphics.setFont(this.defaultFont);
  428.     FontMetrics fm = getFontMetrics(this.defaultFont);
  429.     bufferGraphics.drawText(name, x + 1 + (61 - fm.getTextWidth(name)) / 2,
  430.                                   y + 46 + (16 - fm.getHeight()) / 2);
  431.  
  432.     if (grid.isHighScore(m, s))
  433.     {
  434.       String h = new String("Best Time !");
  435.       bufferGraphics.drawText(h, x + 1 + (61 - fm.getTextWidth(h)) / 2,
  436.                                  y + (16 - fm.getHeight()) / 2);
  437.       Catalog _levels = new Catalog("eCross Levels.eCrs.eCrs", Catalog.WRITE_ONLY);
  438.       _levels.setRecordPos(level);      
  439.       _levels.writeBytes(new byte[] { m, s }, 0, 2);
  440.       _levels.close();
  441.     }
  442.  
  443.     for (int i = 0; i < 15; i++)
  444.     {
  445.       int _y = y + 16 + (i * 2);
  446.       for (int j = 0; j < 15; j++)
  447.       {
  448.         if (picture[i * 15 + j] == 1)
  449.           bufferGraphics.fillRect(x + 16 + (j * 2), _y, 2, 2);
  450.       }
  451.     }
  452.  
  453.     if (++level == levels.getLevelsCount())
  454.       level = 0;
  455.  
  456.     loss = -2;
  457.  
  458.     setLevel();
  459.     state = LEVEL_FINISHED;
  460.     draw();
  461.   }
  462.  
  463.   /**
  464.    * Called by <code>BackCounter</code> when remaining time is out.
  465.    */
  466.  
  467.   public void timeOut()
  468.   {
  469.     int x = 47;
  470.     int y = 15 + 40;
  471.  
  472.     bufferGraphics.setColor(255, 255, 255);
  473.     bufferGraphics.fillRect(x - 1, y - 1, 64, 64);
  474.  
  475.     bufferGraphics.setColor(0, 0, 0);
  476.     bufferGraphics.drawRect(x, y, 62, 62);
  477.  
  478.     bufferGraphics.setFont(this.defaultFont);
  479.     FontMetrics fm = getFontMetrics(this.defaultFont);
  480.     String gameover = new String("Time Out !");
  481.     bufferGraphics.drawText(gameover, x + (62 - fm.getTextWidth(gameover)) / 2,
  482.                                       y + (62 - fm.getHeight()) / 2);
  483.  
  484.     loss = -2;
  485.  
  486.     state = LEVEL_FINISHED;
  487.     grid.reset();
  488.     draw();
  489.     timer.reset();
  490.   }
  491.  
  492.   /**
  493.    * Returns the back buffer drawing surface.
  494.    */
  495.  
  496.   public Graphics getBackBuffer()
  497.   {
  498.     return bufferGraphics;
  499.   }
  500.  
  501.   /**
  502.    * Clears the back buffer.
  503.    */
  504.  
  505.   public void clearBuffer()
  506.   {
  507.     bufferGraphics.setColor(255, 255, 255);
  508.     bufferGraphics.fillRect(0, 0, this.width, this.height);
  509.   }
  510.  
  511.   /**
  512.    * Clears the drawing area.
  513.    */
  514.  
  515.   public void clear()
  516.   {
  517.     g.setColor(255, 255, 255);
  518.     g.fillRect(0, 0, this.width, this.height);
  519.   }
  520.  
  521.   /**
  522.    * Performs the draw of the back buffer onto
  523.    * the drawing area.
  524.    */
  525.  
  526.   public void draw()
  527.   {
  528.     g.drawImage(bufferImage, 0, 0);
  529.   }
  530.  
  531.   /**
  532.    * Paints every component.
  533.    */
  534.  
  535.   public void paint()
  536.   {
  537.     title.paint(this, bufferGraphics);
  538.     selector.paint(this, bufferGraphics);
  539.     info.paint(bufferGraphics);
  540.     wall.paint(bufferGraphics);
  541.  
  542.     grid.drawGrid();
  543.     grid.drawCells();
  544.  
  545.     timer.paint(false);
  546.     tool.paint(bufferGraphics);
  547.     exit.paint(bufferGraphics);
  548.   }
  549.  
  550.   ///////////////////////////////////////////////////////////////////////////////////////////////
  551.   // PRIVATE METHODS
  552.   ///////////////////////////////////////////////////////////////////////////////////////////////
  553.  
  554.   // sets the level by getting it from the LevelsManager.
  555.   // then we display level number and high score on screen.
  556.  
  557.   private void setLevel()
  558.   {
  559.     Level l = levels.getLevel(level);
  560.     grid.setLevel(l);
  561.  
  562.     StringBuffer buf = new StringBuffer("Level ").append(level + 1).append(' ').append('[');
  563.  
  564.     byte[] h = l.getHighScore();
  565.  
  566.     if (h[0] < 10)
  567.       buf.append('0');
  568.     buf.append(h[0]).append(':');
  569.  
  570.     if (h[1] < 10)
  571.       buf.append('0');
  572.  
  573.     selector.setInfo(buf.append(h[1]).append(']').toString());
  574.   }
  575. }
  576.  
  577. // End of eCross.java
  578.